package client

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"io/ioutil"
	"likeadmin/admin/schemas/req"
	"likeadmin/admin/schemas/resp"
	"likeadmin/config"
	"likeadmin/core/request"
	"likeadmin/core/response"
	"likeadmin/model/client"
	"likeadmin/util"
	"net/http"
	"strings"
	"time"
)

type ISourceService interface {
	List(page request.PageReq, listReq req.SourceListReq) (res response.PageResp, e error)
	Detail(id string) (res resp.SourceResp, e error)
	Add(c *gin.Context, addReq req.SourceAddReq) (e error)
	Edit(editReq req.SourceEditReq) (e error)
	Del(id string) (e error)
	AdDelivery(id string) (res resp.SourceAdDeliveryResp, e error)
}

// NewSourceService 初始化
func NewSourceService(db *gorm.DB) ISourceService {
	return &sourceService{db: db}
}

// sourceService 外推服务实现类
type sourceService struct {
	db *gorm.DB
}

// List 外推列表
func (srv sourceService) List(page request.PageReq, listReq req.SourceListReq) (res response.PageResp, e error) {
	// 分页信息
	limit := page.PageSize
	offset := page.PageSize * (page.PageNo - 1)
	// 查询
	model := srv.db.Model(&client.Source{})
	if listReq.Title != "" {
		model = model.Where("title like ?", "%"+listReq.Title+"%")
	}

	if listReq.IsAudit >= 0 {
		model = model.Where("is_audit = ?", listReq.IsAudit)
	}
	model = model.Where("delete_time = ?", 0)
	model = model.Where("account_id = ?", listReq.AccountId)

	// 总数
	var count int64
	err := model.Count(&count).Error
	if e = response.CheckErr(err, "List Count err"); e != nil {
		return
	}
	// 数据
	var objs []client.Source
	err = model.Limit(limit).Offset(offset).Order("create_time desc").Find(&objs).Error
	if e = response.CheckErr(err, "List Find err"); e != nil {
		return
	}
	resps := []resp.SourceResp{}
	response.Copy(&resps, objs)

	return response.PageResp{
		PageNo:   page.PageNo,
		PageSize: page.PageSize,
		Count:    count,
		Lists:    resps,
	}, nil
}

// Detail 外推详情
func (srv sourceService) Detail(id string) (res resp.SourceResp, e error) {
	var obj client.Source
	err := srv.db.Where("source_id = ?", id).Limit(1).First(&obj).Error
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Detail First err"); e != nil {
		return
	}
	response.Copy(&res, obj)

	var drama client.Drama
	err = srv.db.Model(client.Drama{}).Where("drama_id = ?", obj.DramaId).Limit(1).First(&drama).Error
	// 校验
	if e = response.CheckErrDBNotRecord(err, "短剧数据不存在!"); e == nil {
		res.DramaTitle = drama.Title
	}

	return
}

// Add 外推新增
func (srv sourceService) Add(c *gin.Context, addReq req.SourceAddReq) (e error) {
	var obj client.Source

	var account client.Account
	err := srv.db.Where("account_id = ?", addReq.AccountId).Limit(1).First(&account).Error
	// 校验
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Del First err"); e != nil {
		return
	}

	response.Copy(&obj, addReq)

	obj.SourceId = util.UitlSnow.SnowId()
	obj.CreaterID = config.AdminConfig.GetAdminId(c)
	obj.Channel = account.Channel
	obj.PackageName = account.PackageName
	obj.Rebate = account.Rebate

	err = srv.db.Create(&obj).Error
	e = response.CheckErr(err, "Add Create err")
	return
}

// Edit 外推编辑
func (srv sourceService) Edit(editReq req.SourceEditReq) (e error) {
	var obj client.Source
	err := srv.db.Where("source_id = ?", editReq.SourceId).Limit(1).First(&obj).Error
	// 校验
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Edit First err"); e != nil {
		return
	}
	// 更新
	err = srv.db.Model(client.Source{}).Where("source_id = ?", obj.SourceId).Select(
		"title", "gear_type", "series_id", "drama_id", "recharge_template_id", "areas", "is_audit",
	).Updates(client.Source{
		Title:              editReq.Title,
		GearType:           editReq.GearType,
		SeriesId:           editReq.SeriesId,
		DramaId:            editReq.DramaId,
		RechargeTemplateId: editReq.RechargeTemplateId,
		Areas:              editReq.Areas,
		IsAudit:            editReq.IsAudit,
	}).Error

	e = response.CheckErr(err, "Edit Updates err")
	return
}

// Del 外推删除
func (srv sourceService) Del(id string) (e error) {
	var obj client.Source
	err := srv.db.Where("source_id = ?", id).Limit(1).First(&obj).Error
	// 校验
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "Del First err"); e != nil {
		return
	}
	// 删除
	err = srv.db.Model(client.Source{}).Where("source_id = ?", obj.SourceId).Select("delete_time", "is_stop", "is_audit").Updates(&client.Source{
		DeleteTime: time.Now().Unix(),
		IsStop:     1,
		IsAudit:    1,
	}).Error

	e = response.CheckErr(err, "Del Delete err")
	return
}

// AdDelivery
func (srv sourceService) AdDelivery(id string) (res resp.SourceAdDeliveryResp, e error) {
	var obj client.Source
	err := srv.db.Where("source_id = ?", id).Limit(1).First(&obj).Error
	if e = response.CheckErrDBNotRecord(err, "数据不存在!"); e != nil {
		return
	}
	if e = response.CheckErr(err, "AdDelivery Detail First err"); e != nil {
		return
	}

	var appConfigs client.AppConfigs
	err = srv.db.Model(&client.AppConfigs{}).Where("package_name = ? AND status = ?", obj.PackageName, 1).Limit(1).First(&appConfigs).Error
	if e = response.CheckErrDBNotRecord(err, "AdDelivery AppConfigs Find err"); e != nil {
		return
	}

	var resp resp.SourceAdDeliveryResp

	response.Copy(&resp, obj)

	resp.Path = "pages/eat/index?source_id=" + resp.SourceId
	// 1=头条, 2=百度, 3=uc, 4=oppo, 5=vivo, 6=快手
	if resp.Channel == 4 {
		resp.Listening = "https://listening.eeopn.com/client/listening/oppo?os=$os$&os_version=$ov$&model=$m$&lang=$lan$&country=$c$&width=$w$&height=$h$&pkg=$pkg$&app_version=$av$&useragent=$ua$&referer=$rf$&ip=__IP__&net_type=$nt$&carrier=$ca$&progress=$progress$&imei=$im$&oaid=__OAID__&ad_id=$ad$&ad_name=$an$&req_id=$req$&spread_id=" + resp.SourceId
	}
	if resp.Channel == 1 {
		resp.Listening = fmt.Sprintf("https://listening.eeopn.com/client/listening/oceanengine?aid=__AID__&aid_name=__AID_NAME__&cid=__CID__&cid_name=__CID_NAME__&campaign_id=__CAMPAIGN_ID__&campaign_name=__CAMPAIGN_NAME__&ctype=__CTYPE__&advertiser_id=__ADVERTISER_ID__&csite=__CSITE__&convert_id=__CONVERT_ID__&request_id=__REQUEST_ID__&sl=__SL__&os=__OS__&ip=__IP__&ua=__UA__&ts=__TS__&callback_param=__CALLBACK_PARAM__&callback_url=__CALLBACK_URL__&model=__MODEL__&union_site=__UNION_SITE__&promotion_id=__PROMOTION_ID__&project_id=__PROJECT_ID__&promotion_name=__PROMOTION_NAME__&project_name=__PROJECT_NAME__&mid1=__MID1__&mid2=__MID2__&mid3=__MID3__&mid4=__MID4__&mid5=__MID5__&mid6=__MID6__&spread_id=%s&source_id=%s&account_id=%s", resp.SourceId, resp.SourceId, obj.AccountId)

		resp.ListeningGoods = fmt.Sprintf("https://listening.eeopn.com/client/listening/oceanengine?aid=__AID__&aid_name=__AID_NAME__&cid=__CID__&cid_name=__CID_NAME__&campaign_id=__CAMPAIGN_ID__&campaign_name=__CAMPAIGN_NAME__&ctype=__CTYPE__&advertiser_id=__ADVERTISER_ID__&csite=__CSITE__&convert_id=__CONVERT_ID__&request_id=__REQUEST_ID__&sl=__SL__&os=__OS__&ip=__IP__&ua=__UA__&ts=__TS__&callback_param=__CALLBACK_PARAM__&callback_url=__CALLBACK_URL__&model=__MODEL__&union_site=__UNION_SITE__&promotion_id=__PROMOTION_ID__&project_id=__PROJECT_ID__&promotion_name=__PROMOTION_NAME__&project_name=__PROJECT_NAME__&mid1=__MID1__&mid2=__MID2__&mid3=__MID3__&mid4=__MID4__&mid5=__MID5__&mid6=__MID6__&track_id=__TRACK_ID__&imei=__IMEI__&idfa=__IDFA__&androidid=__ANDROIDID__&oaid=__OAID__&caid=__CAID__&outerid=__OUTERID__&spread_id=%s&source_id=%s&account_id=%s", resp.SourceId, resp.SourceId, obj.AccountId)

	}

	resp.AppConfig = appConfigs

	// 生成微信小程序URL Scheme
	urlScheme, err := srv.GenerateWeappUrlScheme(resp.SourceId, resp.AppConfig)
	if err == nil {
		// 转换为H5链接
		resp.LinkUrl = strings.ReplaceAll(urlScheme, "weixin://dl/business/", "https://xwddwc.ssxone.cn/wx.html")
	}

	return resp, nil
}

// GenerateWeappUrlScheme 生成微信小程序URL Scheme
func (srv sourceService) GenerateWeappUrlScheme(sourceId string, appConfig client.AppConfigs) (urlScheme string, e error) {
	// 获取微信access_token
	accessToken, err := srv.getWeappAccessToken(appConfig)
	if err != nil {
		return "", response.CheckErr(err, "获取微信access_token失败")
	}

	// 构造请求URL
	url := fmt.Sprintf("https://api.weixin.qq.com/wxa/generatescheme?access_token=%s", accessToken)

	// 构造请求参数
	requestBody := map[string]interface{}{
		"jump_wxa": map[string]interface{}{
			"path":  "/pages/eat/index",
			"query": "source_id=" + sourceId,
		},
	}

	// 发送POST请求
	jsonData, _ := json.Marshal(requestBody)
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return "", response.CheckErr(err, "调用微信API失败")
	}
	defer resp.Body.Close()

	// 解析响应
	body, _ := ioutil.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)

	// 检查是否成功
	if result["errcode"].(float64) != 0 {
		return "", response.CheckErr(errors.New(result["errmsg"].(string)), "微信API返回错误")
	}

	return result["openlink"].(string), nil
}

// getWeappAccessToken 获取微信小程序access_token
func (srv sourceService) getWeappAccessToken(appConfig client.AppConfigs) (accessToken string, e error) {
	// 这里需要替换为实际的小程序appid和secret
	appid := appConfig.AppId
	secret := appConfig.AppSecret

	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appid, secret)

	resp, err := http.Get(url)
	if err != nil {
		return "", response.CheckErr(err, "获取access_token请求失败")
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)

	if result["errcode"] != nil {
		return "", response.CheckErr(errors.New(result["errmsg"].(string)), "获取access_token失败")
	}

	return result["access_token"].(string), nil
}
